import Point from '../geometry/Point';
import DragRotate from './DragRotate';
import { bindAll } from '../utils/utils';
import Animator from '../animate/Animator';

import MapView from '../view/Panorama';
import { CameraOptions, EventMap } from '../typings/PanoramaType';

type Type = keyof EventMap;

class GestureManager {
    private _mapView: MapView;
    private _dom: HTMLElement;
    private _animator?: Animator;
    private _dragRotate: DragRotate;

    constructor(mapView: MapView) {
        this._mapView = mapView;
        this._dragRotate = new DragRotate(mapView);
        bindAll([
            '_frameUpdate',
            '_onMousedown',
            '_onMousemove',
            '_onMouseup',
            '_onDbClick',
            '_onTouchstart',
            '_onTouchmove',
            '_onTouchend',
            '_onMouseleave',
        ], this);

        this._dom = this._mapView.getCanvasContainer();
        this._dom.addEventListener('mousedown', this._onMousedown);
        this._dom.addEventListener('mousemove', this._onMousemove);
        this._dom.addEventListener('mouseup', this._onMouseup);
        this._dom.addEventListener('mouseleave', this._onMouseleave);
        this._dom.addEventListener('touchstart', this._onTouchstart);
        this._dom.addEventListener('touchmove', this._onTouchmove);
        this._dom.addEventListener('touchend', this._onTouchend);
        this._dom.addEventListener('contextmenu', GestureManager.onContextmenu);
    }

    private static onContextmenu(e: MouseEvent) {
        GestureManager.stopOriginEvent(e);
    }

    getAnimator() {
        return this._animator;
    }

    setAnimator(animator?: Animator) {
        this._animator = animator;
    }

    private _fireEvent(params: CameraOptions, suffix: 'Start' | 'End' | '') {
        const { bearing, pitch } = params;
        this._mapView.fire(<Type>`move${suffix}`);
        typeof bearing === 'number' && this._mapView.fire(<Type>`bearing${suffix}`);
        typeof pitch === 'number' && this._mapView.fire(<Type>`pitch${suffix}`);
    }

    private _onMousedown(e: MouseEvent) {
        GestureManager.stopOriginEvent(e);
        this._dragRotate.onMousedown(e);
    }

    private _onMousemove(e: MouseEvent) {
        GestureManager.stopOriginEvent(e);
        this._dragRotate.onMousemove(e);
        const engine = this._mapView.getEngine();
    }

    private _onMouseup(e: MouseEvent) {
        GestureManager.stopOriginEvent(e);
        this._dragRotate.onMouseup(e);
    }

    private _onMouseleave(e: MouseEvent) {
        this._dragRotate.onMouseleave(e);
    }

    private _onTouchstart(e: TouchEvent) {
        GestureManager.stopOriginEvent(e);
        this._dragRotate.onTouchstart(e);
    }

    private _onTouchmove(e: TouchEvent) {
        GestureManager.stopOriginEvent(e);
        this._dragRotate.onTouchmove(e);
    }

    private _onTouchend(e: TouchEvent) {
        GestureManager.stopOriginEvent(e);
        this._dragRotate.onTouchend(e);
    }

    destroy() {
        this._dom.removeEventListener('mousedown', this._onMousedown);
        this._dom.removeEventListener('mousemove', this._onMousemove);
        this._dom.removeEventListener('mouseup', this._onMouseup);
        this._dom.removeEventListener('mouseleave', this._onMouseleave);
        this._dom.removeEventListener('touchstart', this._onTouchstart);
        this._dom.removeEventListener('touchmove', this._onTouchmove);
        this._dom.removeEventListener('touchend', this._onTouchend);
        this._dom.removeEventListener('contextmenu', GestureManager.onContextmenu);
    }

    disableRotate() {
        this._dragRotate.disableRotate();
    }

    enableRotate() {
        this._dragRotate.enableRotate();
    }

    disablePitch() {
        this._dragRotate.disablePitch();
    }

    enablePitch() {
        this._dragRotate.enablePitch();
    }

    static stopOriginEvent(e: Event) {
        e.stopPropagation();
        e.preventDefault();
    }
}

export default GestureManager;
